package com.hunlian.makelove.update;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DecimalFormat;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.hunlian.makelove.R;

/**
 * IntentService是继承于Service并处理异步请求的一个类，在IntentService内有一个工作线程来处理耗时操作，
 * 启动IntentService的方式和启动传统Service一样，同时，当任务执行完后，
 * IntentService会自动停止，而不需要我们去手动控制。另外，可以启动IntentService多次，
 * 而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行，
 * 并且，每次只会执行一个工作线程，执行完第一个再执行第二个，以此类推。
 * 用IntentService有什么好处呢？首先，我们省去了在Service中手动开线程的麻烦，第二，当操作完成时，我们不用手动停止Service，
 * 
 * bindService()方式启动的Service,必需调用unbindService()方法，Service才会执行onDestroy()方法
 * bindService()方式启动IntentService，IntentService的onHandleIntent()方法并不会执行
 * @author zealjiang
 * @time 2016年2月26日下午2:00:45
 */
public class AppDownloadIntentService extends IntentService {

	private NotificationManager mNotificationManager=null;
	private Notification mNotification;
	private RemoteViews mContentView;
	private static final int notificationId = 19172437;
	private final IBinder mBinder = new MyBinder();
	/**
	 * 是否中止下载;isStopDownload为true表示中止下载，false不中止下载
	 */
	public boolean isStopDownload = false;
	/**
	 * 是否显示通知;isShowNotification为true表示显示，false不显示
	 */
	public boolean isShowNotification = false;
	/**
	 * 只执行一次的标志位
	 */
	public boolean startOnce = true;

	/**
	 * 下载完成的标志位;isDownloadOver为true表示下载完成，false表示没有下载完成
	 */
	private boolean isDownloadOver = false;
	
	/**
	 * 软件没下载完成的后缀
	 */
	private String noLoadOverFileSuffix = ".tmp";
	
	/**
	 * true 表示可以继续下载，false表示停止下载
	 */
	public static boolean canDownload = true;

	/** 需要一个无参数的构造方法，调用父类的带String参数的构造方法，参数是线程名称 */
	public AppDownloadIntentService() {
		super("AppDownloadIntentService");
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		System.out.println("onHandleIntent:  "+canDownload);
		// 提示step
		int downStep = 1;
		// 文件总大小
		int totalSize;
		// 已经下载好的大小
		long downloadCount = 0;
		// 已经上传的文件大小
		int updateCount = 0;

		
		String apkName = intent.getStringExtra("apkName");
		
		if (apkName == null || apkName.length() == 0
				|| apkName.equalsIgnoreCase("null")) {
			return;
		}
		String url = intent.getStringExtra("url");
		if (url == null || url.length() == 0 || url.equalsIgnoreCase("null")) {
			return;
		}
		try {
			
			//第一步：获取要下载的文件的大小
			InputStream is = null;
			URL curl = new URL(url);			
			//获取要下载的文件大小
			HttpURLConnection httpURLConnection = (HttpURLConnection) curl
					.openConnection();
			httpURLConnection.setDoInput(true);
			// 获取下载文件的size
			totalSize = httpURLConnection.getContentLength();
			httpURLConnection.disconnect();
			
			
			//第二步：查看本地是否存在要下载的文件
			File fileDir = new File(Environment.getExternalStorageDirectory(), "klhunlian");
			if (!fileDir.exists()) {
				// 创建一层目录使用mkdir(),多层目录用mkdirs()
				fileDir.mkdir();
			}
			File apkFile = new File(fileDir, apkName);
			File tmpApkFile = new File(fileDir, apkName+noLoadOverFileSuffix);	
				
		
			//判断要下载的文件是不是存在，如果存在就直接安装
			if(apkFile.exists()){				
				//判断网络文件和本地文件的大小是否相同
				if(totalSize!=apkFile.length()){
					//删除该存在的文件
					apkFile.delete();
				}else{	
					//删除旧的无用的文件
					deleteOtherFile(apkFile);
					// 发送广播信息通知更新界面
					// 发送广播信息通知更新界面
					setMsg(100, uniteConversion(apkFile.length()), uniteConversion(apkFile.length()),"",true);
					isDownloadOver = true;	
					Thread.sleep(500);
				}
			}
			
			//System.out.println("isDownloadOver: "+isDownloadOver);
			if (isDownloadOver == false) {
				
				//删除旧的无用的文件
				deleteOtherFile(new File[]{tmpApkFile,apkFile});
				
				RandomAccessFile randomApkFile = new RandomAccessFile(tmpApkFile, "rw");
				long fileSize = 0;
				if (tmpApkFile.exists()) {
					// 获取文件大小
					fileSize = tmpApkFile.length();
					if (fileSize >= totalSize) {
						// 文件已经下载完成
						isDownloadOver = true;
					} else {
						isDownloadOver = false;
					}
	
				} else {
					isDownloadOver = false;
				}
				
				//开启下载连接
				HttpURLConnection httpURLConnection2 = (HttpURLConnection) curl
						.openConnection();
				httpURLConnection2.setDoInput(true);
				httpURLConnection2.setRequestProperty("Range", "bytes="
						+ fileSize + "-" + (totalSize - 1));
				httpURLConnection2.setDoInput(true);
				httpURLConnection2.connect();
				if (httpURLConnection.getResponseCode() == 404) {
					throw new Exception("fail!");
				}

			

				is = httpURLConnection2.getInputStream();
				randomApkFile.seek(fileSize);
				if (is == null) {
					Toast.makeText(this, "网络错误,升级失败!", Toast.LENGTH_LONG)
							.show();
				}


				try {
					// 发送广播信息通知更新界面
					setMsg(0, uniteConversion(0), uniteConversion(totalSize),"",false);

					byte[] b = new byte[1024];
					int count = 0;
					downloadCount = fileSize;
					while ((count = is.read(b)) > 0 && canDownload) {
						if (isStopDownload)
							break;
						randomApkFile.write(b, 0, count);						
						downloadCount += count;
						// 计算进度条位置
						int progress = (int) (((float) downloadCount / totalSize) * 100);
						//System.out.println("isShowNotification:::::::::"+isShowNotification);
						if (updateCount == 0 || (progress - 1 > updateCount)) {
							updateCount += 1;
							String sdownloadedSize = uniteConversion((int)downloadCount);
							String stotalSize = uniteConversion(totalSize);
							
//							String sdownloadedSize = uniteKbConversion((int)downloadCount);
//							String stotalSize = uniteKbConversion(totalSize);

							if (progress == 0) {
								sdownloadedSize = "0";
							}
							//System.out.println(this+"    "+isShowNotification+"-----downloading----"+progress);
							if (isShowNotification) {
								if (startOnce) {
									// 创建通知栏
									createNotification();
									startOnce = false;
								}

								mContentView.setTextViewText(
										R.id.notification_loaded_percent,
										progress + "%");
								mContentView.setTextViewText(
										R.id.notification_loaded_size,
										sdownloadedSize+"");
								mContentView.setTextViewText(
										R.id.notification_total_size,
										stotalSize+"");
								mContentView.setProgressBar(
										R.id.notification_progress, 100,
										updateCount, false);
								mNotificationManager.notify(notificationId,
										mNotification);

								//System.out.println("-------------downloading-----------------"+progress);
							}

							// 发送广播信息通知更新界面
							setMsg(progress, sdownloadedSize, stotalSize, "",false);
							if (progress == 100) {
								isDownloadOver = true;
							}
						}

					}
				} catch (IOException e) {
					e.printStackTrace();
					//System.out.println("download error:" + e.getMessage());
					// 发送广播信息通知更新界面
					setMsg(0, "0", "0", "网络连接出错",false);
				} catch (Exception e) {
					e.printStackTrace();
					//System.out.println("download error:" + e.getMessage());
					// 发送广播信息通知更新界面
					setMsg(0, "0", "0", "",false);
				} finally {
					if (randomApkFile != null) {
						randomApkFile.close();
					}
					if (is != null) {
						is.close();
					}
				}
			}
			// Cancel a previously shown notification. If it's transient, the
			// view will be hidden.
			// If it's persistent, it will be removed from the status bar.

			//System.out.println("........isShowNotification......" + isShowNotification);
			// 清楚通知栏
			clearNotification();

			if (!isStopDownload && isDownloadOver) {
				if(!apkFile.exists()&&tmpApkFile!=null){
					//重命名
					tmpApkFile.renameTo(apkFile);
				}

				installApkFile(apkFile);
			}

			/**
			 * 任务结束后会自行关闭，无需stopSelf()
			 *  关闭service
			 */
			//stopSelf();
			 

		} catch (Exception e) {
			// Toast.makeText(this, "网络错误,升级失败!", Toast.LENGTH_SHORT).show();
			e.printStackTrace();
			// 发送广播信息通知更新界面
			setMsg(0, "0", "0", "网络连接出错",false);
		}
		

		if(mAppDownloadManager!=null){
			mAppDownloadManager.unboundService();
		}
	}
	

	public void createNotification() {
		mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
		mNotification = new Notification();
		// 发送通知时，状态栏上显示的图标
		mNotification.icon = R.drawable.ic_launcher;
		// 发送通知时，状态栏滚动的文字信息
		mNotification.tickerText = "伉俪婚恋正在下载...";
		// 点击通知item的意图
		Intent intent = new Intent(this, AppDownloadIntentService.class);
		PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
				intent, 0);
		// 初始化通知栏
		mContentView = new RemoteViews(getPackageName(),
				R.layout.setting_item_notification_update_icon);

		// mContentView.setTextViewText(R.id.notification_title, "正在下载");
		mContentView.setTextViewText(R.id.notification_loaded_percent, "0%");
		mContentView.setTextViewText(R.id.notification_loaded_size, "0");
		mContentView.setTextViewText(R.id.notification_total_size, "0");
		mContentView.setProgressBar(R.id.notification_progress, 100, 0, false);

		mNotification.contentView = mContentView;
		mNotification.contentIntent = pendingIntent;
		// 设置不被清楚
		mNotification.flags |= Notification.FLAG_NO_CLEAR;
		mNotificationManager.notify(notificationId, mNotification);

		// mContentView.setOnClickPendingIntent(viewId, pendingIntent)
	}

	private String getApkName(String path) {
		int index = path.indexOf("filename=");
		if (index < 0) {
			return "tourUpdateVersion.apk";
		} else {
			return path.substring(index + "filename=".length(), path.length());
		}
	}

	/** 安装apk */
	public void installApkFile(File file) {
		Intent intent = new Intent();
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		intent.setAction(Intent.ACTION_VIEW);
		intent.setDataAndType(Uri.fromFile(file),
				"application/vnd.android.package-archive");
		startActivity(intent);
	}

	/**
	 * 发送下载进度信息
	 * 
	 * @param curPercent
	 *            当前已下载好的百分比
	 * @param curSize
	 *            当前已下载好的大小
	 * @param totalSize
	 *            总大小
	 * @param error
	 *            错误信息，没有错误，此参数值为""
	 */
	public void setMsg(int curPercent, String curSize, String totalSize,
			String error,boolean isDalay) {
		Intent intent = new Intent(this.getPackageName());
		intent.putExtra("curPercent", curPercent);
		intent.putExtra("curSize", curSize);
		intent.putExtra("totalSize", totalSize);
		intent.putExtra("error", error);
		intent.putExtra("delay", isDalay);
		sendBroadcast(intent);
	}

	/**
	 * 单位转换
	 * 
	 * @param size
	 *            单位为bit的大小
	 * @return 返回kb或Mb为单位的值
	 */
	public String uniteConversion(long size) {
		long m = size / (1024 * 1024);
		String unite = "";
		double formatSize;
		if (m < 1) {
			// size小于1M
			formatSize = size / 1024d;
			unite = "kb";
		} else {
			// size大于1M
			formatSize = size / (1024 * 1024d);
			unite = "Mb";
		}

		DecimalFormat df = new DecimalFormat("#0.0");
		String value = df.format(formatSize);
		double remainder = Double.valueOf(value) % 1;
		if (remainder == 0) {
			return (int) formatSize + unite;
		} else {
			return df.format(formatSize) + unite;
		}

	}
	/**
	 * 单位转换
	 * @param 
	 * @return 返回已KB为单位的值
	 */
	public String uniteKbConversion(long size){
		long m = size / (1024 * 1024);
		String unite = "";
		double formatSize;
		
		formatSize = size / 1024d;
		unite = "kb";
		DecimalFormat df = new DecimalFormat("#0.0");
		String value = df.format(formatSize);
		double remainder = Double.valueOf(value) % 1;
		if (remainder == 0) {
			return (int) formatSize + unite;
		} else {
			return df.format(formatSize) + unite;
		}
	}

	class MyBinder extends Binder {
		public AppDownloadIntentService getService() {
			return AppDownloadIntentService.this;
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	@Override
	public boolean onUnbind(Intent intent) {
		return super.onUnbind(intent);
	}

	@Override
	public void onRebind(Intent intent) {
		super.onRebind(intent);
	}
	
	private AppDownloadManager mAppDownloadManager;
	public void setAppDownloadManager(AppDownloadManager am){
		mAppDownloadManager = am;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		//System.out.println("---onStartCommand---"+this);
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if(mNotificationManager!= null){
			mNotificationManager.cancel(notificationId);
		}
		//System.out.println("---onDestroy---"+this);
	}

	/**
	 * 清楚通知栏
	 */
	public void clearNotification() {
		if (isShowNotification) {
			try {
				mNotificationManager.cancel(notificationId);
			} catch (Exception e) {
				Toast.makeText(getApplicationContext(), e.getMessage(), 0)
						.show();
			}

		}
	}
	
	/**
     * 
     * author zealjiang
     * time 2014年10月17日 下午1:56:53
     * note: 删除与file同目录下的其它文件
     * @param file
     */
    public void deleteOtherFile(File file) {  
    	   	
    	if(file==null)return;
    	File parentFile = file.getParentFile();
        if (parentFile.isFile()) {  
            return;  
        }  
  
        if(parentFile.isDirectory()){  
            File[] childFiles = parentFile.listFiles();  
            if (childFiles == null || childFiles.length == 0) {  
                return;  
            }  
      
            for (int i = 0; i < childFiles.length; i++) {  
                if(!file.getName().equals(childFiles[i].getName())){
                	childFiles[i].delete();         
                }  
            }  
        }  
    }
    
    /**
     * 
     * author zealjiang
     * time 2014年10月17日 下午1:56:53
     * note: 删除与file同目录下的其它文件
     * @param files 删除除files数组中包含的文件外之外的所有文件
     */
    public static void deleteOtherFile(File[] files) {  
    	   	
    	if(files==null)return;
    	if(files.length==0)return;
    	File parentFile = files[0].getParentFile();
        if (parentFile.isFile()) {  
            return;  
        }  
  
        if(parentFile.isDirectory()){  
            File[] childFiles = parentFile.listFiles();  
            if (childFiles == null || childFiles.length == 0) {  
                return;  
            }  
      
            for (int i = 0; i < childFiles.length; i++) { 
            	boolean tag = false;
            	for(int j = 0; j < files.length; j++){
                    if(files[j].getName().equals(childFiles[i].getName())){
                    	tag = true;
                    	break;
                    } 
            	}
            	if(!tag)
            		childFiles[i].delete();  
            }  
        }  
    }
}
